/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs     (C)ChaN, 2016        */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be        */
/* attached to the FatFs via a glue function rather than modifying it.   */
/* This is an example of glue functions to attach various exsisting      */
/* storage control modules to the FatFs module with a defined API.       */
/*-----------------------------------------------------------------------*/
//#include "pincfg.h"
#include "sdcard.h"	
#include "diskio.h"		/* FatFs lower layer API */

/* Definitions of physical drive number for each drive */

#define DEV_MMC		0	/* Example: Map MMC/SD card to physical drive 1 */
#define DEV_USB		1	

static volatile DSTATUS SdStat = STA_NOINIT;	          /* Disk status */

/*-----------------------------------------------------------------------*/
/* Get Drive Status                                                      */

/*-----------------------------------------------------------------------*/

DSTATUS disk_status(
        BYTE pdrv /* Physical drive nmuber to identify the drive */
        ) {
    DSTATUS stat;
    //int result;

    switch (pdrv) {
        case DEV_MMC:/*
            if(SD_CD_ST()){
                SdStat |= STA_NODISK;
                SdStat |= STA_NOINIT;
            } else {
                SdStat &= ~STA_NODISK;
            }
            */
            stat = SdStat;
            break;
        case DEV_USB:
            //result = USB_disk_status();

            // translate the reslut code here

            stat = RES_PARERR;
            break;
        default:
            stat = RES_PARERR;
            break;
    }

    return stat;
}


/*-----------------------------------------------------------------------*/
/* Inidialize a Drive                                                    */

/*-----------------------------------------------------------------------*/

DSTATUS disk_initialize(
        BYTE pdrv /* Physical drive nmuber to identify the drive */
        ) {
    DSTATUS stat = STA_NOINIT;
    sd_error_enum result;

    switch (pdrv) {
        case DEV_MMC:
            result = sd_init();
            // translate the reslut code here
            if (SD_OK == result){
                SdStat &= ~STA_NOINIT;
            } 
            
            stat = SdStat;
            break;
        case DEV_USB:
            //result = USB_disk_initialize();

            // translate the reslut code here

            stat = RES_PARERR;
            break;
        default:
            stat = RES_PARERR;
            break;
    }
    return stat;
}



/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                        */

/*-----------------------------------------------------------------------*/

DRESULT disk_read(
        BYTE pdrv, /* Physical drive nmuber to identify the drive */
        BYTE *buff, /* Data buffer to store read data */
        DWORD sector, /* Start sector in LBA */
        UINT count /* Number of sectors to read */
        ) {
    DRESULT res;
    sd_error_enum result;

        
    switch (pdrv) {
        case DEV_MMC:
            // translate the arguments here
            if (!count) return RES_PARERR;
            if (SdStat & STA_NOINIT) return RES_NOTRDY;
            
            if(1 == count)
                result = sd_block_read((uint32_t*)buff, sector, 512);
            else
                result = sd_multiblocks_read((uint32_t*)buff, sector, 512, count);

            
            if (SD_OK == result)
                res = RES_OK;
            else
                res = RES_ERROR;
            break;
        case DEV_USB:
            // translate the arguments here

            //result = USB_disk_read(buff, sector, count);

            // translate the reslut code here
            res = RES_PARERR;
            break;
        default:
            res = RES_PARERR;
            break;
    }


    return res;
}



/*-----------------------------------------------------------------------*/
/* Write Sector(s)                                                       */

/*-----------------------------------------------------------------------*/

DRESULT disk_write(
        BYTE pdrv, /* Physical drive nmuber to identify the drive */
        const BYTE *buff, /* Data to be written */
        DWORD sector, /* Start sector in LBA */
        UINT count /* Number of sectors to write */
        ) {
    DRESULT res = RES_PARERR;
    int result;

    switch (pdrv) {
        case DEV_MMC:
            // translate the arguments here
            if (!count) return RES_PARERR;
            if (SdStat & STA_NOINIT) return RES_NOTRDY;
            if(1==count)
                result = sd_block_write((uint32_t*) buff, sector, 512);
            else
                result = sd_multiblocks_write((uint32_t*) buff, sector, 512, count);

            if (SD_OK == result)
                res = RES_OK;
            else
                res = RES_ERROR;

            return res;
            break;
        case DEV_USB:
            // translate the arguments here

            //result = USB_disk_write(buff, sector, count);

            // translate the reslut code here

            res = RES_PARERR;
            break;

        default:
            res = RES_PARERR;
            break;
    }


    return RES_PARERR;
}



/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions                                               */

/*-----------------------------------------------------------------------*/

DRESULT disk_ioctl(
        BYTE pdrv, /* Physical drive nmuber (0..) */
        BYTE cmd, /* Control code */
        void *buff /* Buffer to send/receive control data */
        ) {
    DRESULT res = RES_PARERR;
    //int result;

    switch (pdrv) {
        case DEV_MMC:

            // Process of the command for the MMC/SD card

            return res;
            break;
        case DEV_USB:

            // Process of the command the USB drive

            res = RES_PARERR;
            break;
        default:
            res = RES_PARERR;
            break;
    }

    return RES_PARERR;
}

